package com.jingyong.infosite.service;

import com.jingyong.infosite.dto.response.LoanGradeResponse;
import com.mongodb.BasicDBObject;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
 * @author Hill Dong
 * @date 2018/1/23
 */
@Service
public class LoanGradeService {
	private static final int GRADE_MONTH_NUM = 20;
	Logger logger = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private MongoTemplate mongoTemplate;
	private static final String LOAN_GRADE_DATABASE_NAME = "all_ratings";
	private static final String BIGCITY_GRADE_DATABASE_NAME = "bsg_ratings";
	private static final String FINANCE_SYSTEM_GRADE_DATABASE_NAME = "vcs_ratings";

	public LoanGradeResponse getLoanGradeResponse() {
		LoanGradeResponse response = new LoanGradeResponse();
		Document latestData = getGradeDataLatest();
		if (latestData == null) {
			return response;
		}
		// the latest month
		Integer latestMonth = 0;

		// get top 20 grade data from all
		Object gradeData;

		// all months in mongo
		List<String> monthList = new ArrayList<>();

		// name list in up & down board
		Object upDownList;
		if (latestData != null) {
			Document rawData = (Document) latestData.get("data");
			upDownList = rawData.get("list");
			Set<String> years = rawData.keySet();
			if (years != null && years.size() > 0) {
				for (String s : years) {
					if (isStrToLong(s)) {
						Integer month = new Integer(s);
						if (month > latestMonth) {
							latestMonth = month;
						}
						monthList.add(s);
					} else {
						continue;
					}
				}
			} else {
				logger.error("no grade data");
			}

			monthList.sort(new Comparator<String>() {
				@Override
				public int compare(String o1, String o2) {
					Integer l1 = new Integer(o1);
					Integer l2 = new Integer(o2);
					return (l2 - l1);
				}
			});

			// rawData.get(latestMonth + "");
			List<Object> monthDatas = (List<Object>) rawData.get(latestMonth + "");
			if (monthDatas.size() >= GRADE_MONTH_NUM) {
				gradeData = monthDatas.subList(0, GRADE_MONTH_NUM);
			} else {
				gradeData = monthDatas;
			}
			response.setGradeData(gradeData);
			response.setMonthList(monthList);
			response.setLatestMonth(latestMonth + "");
			response.setUpDownList(upDownList);

			// put grade data from beijing,shanghai and guangzhou
			response.setBigCityGradeData(getBigCityGradeDataLatest().get("data"));

			// put grade data from finance system
			response.setFinanceSystemGradeData(getFinanceSystemGradeDataLatest().get("data"));
		}
		return response;
	}

	private boolean isStrToLong(String s) {
		try {
			Long.parseLong(s);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	public Object getLoanGradeResponseByMonth(String month) {
		Document latestData = getGradeDataLatest();
		Object gradeData = null;
		if (latestData != null) {
			Document rawData = (Document) latestData.get("data");
			List<Object> monthDatas = (List<Object>) rawData.get(month);
			if (monthDatas == null) {
				logger.info("no data for the month " + month);
				return gradeData;
			}
			if (monthDatas.size() >= GRADE_MONTH_NUM) {
				gradeData = monthDatas.subList(0, GRADE_MONTH_NUM);
			} else {
				gradeData = monthDatas;
			}
		}
		return gradeData;
	}

	public Document getGradeDataLatest() {
		return getLatestMongoData(LOAN_GRADE_DATABASE_NAME);
	}

	public Document getBigCityGradeDataLatest() {
		return getLatestMongoData(BIGCITY_GRADE_DATABASE_NAME);
	}

	public Document getLatestMongoData(String dbName) {
		try {
			MongoCollection<Document> coll = mongoTemplate.getCollection(dbName);
			FindIterable<Document> dbIter = coll.find().limit(1).sort(new BasicDBObject("creat_time", -1));
			MongoCursor<Document> cursor = dbIter.iterator();
			if (!cursor.hasNext()) {
				return null;
			}
			return cursor.next();
		} catch (Exception e) {
			logger.error("fail to get latest grade error from" + dbName, e);
			return null;
		}

	}

	public Document getFinanceSystemGradeDataLatest() {
		return getLatestMongoData(FINANCE_SYSTEM_GRADE_DATABASE_NAME);
	}

}
